Typst: 連続して掲げられる見出しの間の行間を詰める
背景:章見出しの前にも節見出しの前にも行間を設けている場合、通常は、章見出しと節見出しの間の行間が詰まらない。
https://gyazo.com/2d98e7a6e44aecee60ef76b04dc0ca03
この場合、章見出しの前の切れ目よりも、節見出しの前の切れ目の方が広く見えるので、情報構造を正しく表現できている組体裁であるとは言えない。
目的:節見出しが章見出しに続けて掲げられる場合だけ、節見出しの前の行間を詰めて、以下の画像のようにしたい。
https://gyazo.com/52d2b7644ec672c37ab25962ed7bc91d
実装の方針
以下のTypstのマークアップは、
code:typ
#import "@preview/roremu:0.1.0": roremu = 2行取りの章見出し
*2行取りの章見出しでは,前後に0.5行分の行間を設ける。*#roremu(48)
== 節見出し
*節見出しでは,前に1行分の行間を設ける。*#roremu(55)
= 2行取りの章見出し
== 節見出し
*節見出しが章見出しに続けて掲げられる場合にも,前に1行分の行間があると,章見出しの前の切れ目よりも,節見出しの前の切れ目の方が広く見えて,不自然である。*
以下と同義である(上のマークアップをrepr([])で囲むとわかる)。
段落を改めるために空行を挿入すると、parbreak()という関数を呼んだのと同じことになる。
code:typ
)
parbreak()の出現回数を数えて、
ある見出しから次の見出しまでにparbreak()が1つしかないなら、見出しが連続して掲げられていることになる。
ある見出しから次の見出しまでにparbreak()が2つ以上あるなら、間に何かしらの文章があることになる。
実装
code:typ
// 次の見出しまでのparbreak()の数を覚えさせる。
#let dist-from-heading = state("mgn901-paper.dist-from-heading", 0) // 見出し内部のparbreak()は無視するために、パーサのポインタの居場所が見出し内部であるか否かを覚えさせる。
#let inside-of-heading = state("mgn901-paper.inside-of-heading", false) #show selector(parbreak): it => { context {
if inside-of-heading.get() == false {
// パーサのポインタが見出しの外にいるなら、parbreak()の数を1増やす。
dist-from-heading.update(dist-from-heading.get() + 1)
}
}
it
}
// パーサのポインタが見出しの中にいることを覚えさせる。
inside-of-heading.update(true)
// ここに見出しの見た目を調整するためのコードを書く。
// parbreak()の数を覚えさせるためのカウンタをリセットする。
dist-from-heading.update(0)
// パーサのポインタが見出しの外に出たことを覚えさせる。
inside-of-heading.update(false)
}
contextを多用しているので、Tinymistを使っていると、見出し周辺の内容を編集したときにTinymist Previewの再描画が重くなってしまうという弱点がある。mgn901.icon